/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package analiseSintatica.Regras.Expressoes;

import analiseSintatica.Regras.*;
import AnaliseLexicaFinal.EstruturaDeDados.LinkToken;
import analiseSintatica.ErroSintaticoException;
import analiseSintatica.estruturadados.ErroSintatico;
import analiseSintatica.estruturadados.NoArvore;
import java.util.LinkedList;

/**
 *
 * @author linton
 */
public class RegraAtribuicao extends Regra{

    protected static Regra instancia;

    protected String estrutura = "{<variavel> '='}+ <expressao>";

    /**
     * Construtor privado necessario ao singleton
     */
    private RegraAtribuicao() {
    }

    /**
     * Retorna a unica instancia dessa classe.
     * @return
     */
    public static RegraAtribuicao getInstance() {
        if (instancia == null) {
            instancia = new RegraAtribuicao();
        }
        return (RegraAtribuicao) instancia;
    }

    @Override
    public NoArvore analisar(LinkedList<LinkToken> tokens) throws ErroSintaticoException {
    	ErroSintaticoException erros = new ErroSintaticoException();

        NoArvore naoterminalatribuicao = new NoArvore("<atribuicao>", false);
        do{
        	try {
        		naoterminalatribuicao.adicionaFilho( RegraVariavel.getInstance().analisar(tokens));
            } catch (ErroSintaticoException e) {
                while (e.size() != 0) {
                    erros.addErros(e.getErros());
                }
            }
            
            try {
            	naoterminalatribuicao.adicionaFilho(reconheceLexema(tokens, "operador_igualdade", "=",estrutura));
            } catch (ErroSintaticoException e) {
                ErroSintatico erro = e.getErros();
                erro.setCorreto(estrutura);
                erros.addErros(erro);
                LinkedList<String> sincronizacao = RegraVariavel.getInstance().getPrimeiro();
                LinkedList<String> sincronizacao2 = RegraExpressao.getInstance().getPrimeiro();
                sincronizacao = getUniao(sincronizacao, sincronizacao2);
                while (!listaContem(sincronizacao, tokens.getFirst())) {
                    erros.addErros("Token " + tokens.getFirst().getToken() + " nao permitido", estrutura, tokens.getFirst().getLinha());
                    tokens.removeFirst();
                }
            }
        }while(this.getPrimeiro().contains(tokens.getFirst().getLexema())||
                this.getPrimeiro().contains(tokens.getFirst().getToken()));
        
        try {
        	naoterminalatribuicao.adicionaFilho(RegraExpressao.getInstance().analisar(tokens));
        } catch (ErroSintaticoException e) {
            while (e.size() != 0) {
                erros.addErros(e.getErros());
            }
        }
        
        if (erros.size() != 0) {
            throw erros;
        }

        return naoterminalatribuicao;
    }

    protected void setPrimeiro() {
      //  this.primeiro = RegraVariavel.getInstance().getPrimeiro();
        /*P(atribuicao) = P(variavel)
             ->P(atribuicao)= { '*' } U { 'identificador' }*/
        this.primeiro.add("*");
        this.primeiro.add("identificador");
    }

    protected void setSeguinte() {
       /* this.seguinte = RegraInstrucao.getInstance().getSeguinte();
        LinkedList<String> temp = new LinkedList<String>();
        temp.add(")");
        temp.add(";");
        this.seguinte = getUniao(this.seguinte, temp);*/

        /*S<atribuicao> = { ";",  ")"}*/
        this.seguinte.add(";");
        this.seguinte.add(")");
    }

   

}
